﻿// Copyright (c) 2024 IndustrialTBB Framework
// Modular TBB-native industrial framework example

#include <oneapi/tbb.h>
#include <oneapi/tbb/parallel_for_each.h>

#include <chrono>
#include <iomanip>
#include <iostream>
#include <memory>
#include <random>
#include <thread>
#include <variant>
#include <vector>

// 包含我们的TBB工业框架
#include "itbb/config/tbb_dynamic_config.h"
#include "itbb/core/tbb_framework.h"
#include "itbb/devices/tbb_adwin_device.h"
#include "itbb/devices/tbb_device_pool.h"

using namespace std::chrono_literals;

// === 独立单元1: 连接进度显示 ===
void Unit1_ConnectionProgress(itbb::IndustrialFramework& framework,
                              std::future<bool>& connect_future) {
  std::cout << "[Unit1] 测试连接进度显示..." << std::endl;

  try {
    framework.SubmitTask([&connect_future]() mutable {
      for (int i = 0; i < 10; ++i) {
        std::this_thread::sleep_for(500ms);
        if (connect_future.wait_for(0ms) == std::future_status::ready) {
          break;
        }
        std::cout << "连接中..." << (i + 1) * 10 << "%" << std::endl;
      }
      std::cout << "[Unit1] 连接进度显示完成" << std::endl;
    });
  } catch (const std::exception& e) {
    std::cout << "[Unit1] 异常: " << e.what() << std::endl;
  }
}

// === 独立单元2: 高频数据采集 ===
void Unit2_HighFreqDataCollection(
    itbb::IndustrialFramework& framework,
    std::shared_ptr<itbb::TbbAdwinDevice> adwin_device) {
  std::cout << "[Unit2] 测试高频数据采集..." << std::endl;

  try {
    framework.AddPeriodicTask(
        "HighFreqDataCollection", 10ms, [adwin_device, &framework]() {
          // 异步读取数据
          auto read_future = adwin_device->ReadDataArrayAsync(1, 0, 100);

          // 使用 shared_ptr 包装 future
          auto shared_future =
              std::make_shared<std::decay_t<decltype(read_future)>>(
                  std::move(read_future));

          // 非阻塞方式处理结果
          framework.SubmitTask([shared_future]() {
            try {
              auto result = shared_future->get();
              if (result.success.load()) {
                std::cout << "[Unit2] 数据读取成功" << std::endl;
              } else {
                static std::atomic<int> error_count{0};
                if (error_count.fetch_add(1) % 100 == 0) {
                  std::cout << "[Unit2] 数据读取失败: " << result.error_message
                            << std::endl;
                }
              }
            } catch (const std::exception& e) {
              std::cout << "[Unit2] 数据处理异常: " << e.what() << std::endl;
            }
          });
        });

    std::cout << "[Unit2] 高频数据采集任务已启动" << std::endl;
  } catch (const std::exception& e) {
    std::cout << "[Unit2] 异常: " << e.what() << std::endl;
  }
}

// === 独立单元3: 设备健康监控 ===
void Unit3_DeviceHealthMonitoring(
    itbb::IndustrialFramework& framework,
    std::shared_ptr<itbb::TbbAdwinDevice> adwin_device) {
  std::cout << "[Unit3] 测试设备健康监控..." << std::endl;

  try {
    framework.AddPeriodicTask(
        "DeviceHealthMonitoring", 2000ms, [adwin_device, &framework]() {
          auto ping_future = adwin_device->PingAsync(1000ms);

          // 使用 shared_ptr 包装 future
          auto shared_ping_future =
              std::make_shared<std::decay_t<decltype(ping_future)>>(
                  std::move(ping_future));

          framework.SubmitTask([shared_ping_future, adwin_device,
                                &framework]() {
            try {
              bool ping_ok = shared_ping_future->get();
              auto& config = itbb::GlobalConfigManager::GetInstance();

              if (ping_ok) {
                config.SetConfig("device.adwin.health", 100.0);
                std::cout << "[Unit3] 设备健康检查通过" << std::endl;
              } else {
                std::cout << "[Unit3] 设备连接异常，启动恢复程序..."
                          << std::endl;
                config.SetConfig("device.adwin.health", 0.0);

                // 触发错误恢复
                auto& error_manager = framework.GetErrorManager();
                std::runtime_error error("Device ping failed");
                error_manager.HandleError("ADwin-1", error);

                // 异步重连
                auto reconnect_future = adwin_device->ConnectAsync();
                auto shared_reconnect =
                    std::make_shared<std::decay_t<decltype(reconnect_future)>>(
                        std::move(reconnect_future));

                framework.SubmitTask([shared_reconnect]() {
                  bool reconnected = shared_reconnect->get();
                  if (reconnected) {
                    std::cout << "[Unit3] 设备重连成功" << std::endl;
                  } else {
                    std::cout << "[Unit3] 设备重连失败" << std::endl;
                  }
                });
              }
            } catch (const std::exception& e) {
              std::cout << "[Unit3] 健康检查异常: " << e.what() << std::endl;
            }
          });
        });

    std::cout << "[Unit3] 设备健康监控任务已启动" << std::endl;
  } catch (const std::exception& e) {
    std::cout << "[Unit3] 异常: " << e.what() << std::endl;
  }
}

// === 独立单元4: 批量数据处理 ===
void Unit4_BatchDataProcessing(
    itbb::IndustrialFramework& framework,
    std::shared_ptr<itbb::TbbAdwinDevice> adwin_device) {
  std::cout << "[Unit4] 测试批量数据处理..." << std::endl;

  try {
    framework.SubmitTask([adwin_device, &framework]() {
      std::this_thread::sleep_for(2s);  // 等待系统稳定

      // 准备批量读取地址
      std::vector<itbb::TbbDataAddress> addresses;
      for (int i = 1; i <= 10; ++i) {
        addresses.emplace_back("Data_" + std::to_string(i));
      }

      std::cout << "[Unit4] 执行批量读取操作..." << std::endl;

      // 批量读取
      auto batch_future = adwin_device->BatchReadAsync(addresses);

      try {
        auto results = batch_future.get();
        std::cout << "[Unit4] 批量读取完成，处理 " << results.size()
                  << " 个结果" << std::endl;

        std::atomic<int> success_count{0};
        // 使用TBB并行处理结果
        tbb::parallel_for_each(
            results.begin(), results.end(),
            [&success_count](const itbb::TbbOperationResult& result) {
              if (result.success.load()) {
                success_count.fetch_add(1, std::memory_order_relaxed);
              }
            });

        std::cout << "[Unit4] 批量处理统计: " << success_count.load() << "/"
                  << results.size() << " 成功" << std::endl;
      } catch (const std::exception& e) {
        std::cout << "[Unit4] 批量处理异常: " << e.what() << std::endl;
      }
    });

    std::cout << "[Unit4] 批量数据处理任务已提交" << std::endl;
  } catch (const std::exception& e) {
    std::cout << "[Unit4] 异常: " << e.what() << std::endl;
  }
}

// === 独立单元5: 数据写入 ===
void Unit5_DataWriting(itbb::IndustrialFramework& framework,
                       std::shared_ptr<itbb::TbbAdwinDevice> adwin_device) {
  std::cout << "[Unit5] 测试数据写入..." << std::endl;

  try {
    framework.AddPeriodicTask("DataWrite", 500ms, [adwin_device, &framework]() {
      // 生成测试数据
      static std::random_device rd;
      static std::mt19937 gen(rd());
      static std::uniform_int_distribution<> dis(0, 999);

      std::vector<int32_t> test_data;
      test_data.reserve(50);
      for (int i = 0; i < 50; ++i) {
        test_data.push_back(dis(gen));
      }

      auto write_future = adwin_device->WriteDataArrayAsync(2, 0, test_data);

      // 使用 shared_ptr 包装 future
      auto shared_write_future =
          std::make_shared<std::decay_t<decltype(write_future)>>(
              std::move(write_future));

      framework.SubmitTask([shared_write_future]() {
        try {
          auto result = shared_write_future->get();
          if (!result.success.load()) {
            static std::atomic<int> write_error_count{0};
            if (write_error_count.fetch_add(1) % 50 == 0) {
              std::cout << "[Unit5] 数据写入失败: " << result.error_message
                        << std::endl;
            }
          }
        } catch (const std::exception& e) {
          std::cout << "[Unit5] 写入异常: " << e.what() << std::endl;
        }
      });
    });

    std::cout << "[Unit5] 数据写入任务已启动" << std::endl;
  } catch (const std::exception& e) {
    std::cout << "[Unit5] 异常: " << e.what() << std::endl;
  }
}

// === 独立单元6: 进程控制测试 ===
void Unit6_ProcessControl(itbb::IndustrialFramework& framework,
                          std::shared_ptr<itbb::TbbAdwinDevice> adwin_device) {
  std::cout << "[Unit6] 测试进程控制..." << std::endl;

  try {
    framework.SubmitTask([adwin_device]() {
      std::this_thread::sleep_for(1s);

      std::cout << "[Unit6] 启动ADwin进程1..." << std::endl;
      auto start_future = adwin_device->StartProcessAsync(1);
      bool started = start_future.get();

      if (started) {
        std::cout << "[Unit6] 进程1启动成功" << std::endl;

        std::this_thread::sleep_for(2s);

        std::cout << "[Unit6] 停止ADwin进程1..." << std::endl;
        auto stop_future = adwin_device->StopProcessAsync(1);
        bool stopped = stop_future.get();

        if (stopped) {
          std::cout << "[Unit6] 进程1停止成功" << std::endl;
        } else {
          std::cout << "[Unit6] 进程1停止失败" << std::endl;
        }
      } else {
        std::cout << "[Unit6] 进程1启动失败" << std::endl;
      }
    });

    std::cout << "[Unit6] 进程控制任务已提交" << std::endl;
  } catch (const std::exception& e) {
    std::cout << "[Unit6] 异常: " << e.what() << std::endl;
  }
}

// === 独立单元7: 参数批量读取 ===
void Unit7_BatchParameterReading(
    itbb::IndustrialFramework& framework,
    std::shared_ptr<itbb::TbbAdwinDevice> adwin_device) {
  std::cout << "[Unit7] 测试参数批量读取..." << std::endl;

  try {
    framework.SubmitTask([adwin_device]() {
      std::this_thread::sleep_for(3s);

      std::cout << "[Unit7] 执行参数批量读取..." << std::endl;
      std::vector<int> param_numbers = {1, 2, 3, 4, 5, 10, 15, 20};

      auto batch_param_future =
          adwin_device->BatchReadParametersAsync(param_numbers);

      try {
        auto param_results = batch_param_future.get();
        std::cout << "[Unit7] 参数批量读取完成，结果数量: "
                  << param_results.size() << std::endl;

        int param_success = 0;
        for (size_t i = 0; i < param_results.size(); ++i) {
          if (param_results[i].success.load()) {
            param_success++;
          }
        }
        std::cout << "[Unit7] 参数读取统计: " << param_success << "/"
                  << param_results.size() << " 成功" << std::endl;
      } catch (const std::exception& e) {
        std::cout << "[Unit7] 参数批量读取异常: " << e.what() << std::endl;
      }
    });

    std::cout << "[Unit7] 参数批量读取任务已提交" << std::endl;
  } catch (const std::exception& e) {
    std::cout << "[Unit7] 异常: " << e.what() << std::endl;
  }
}

// === 独立单元8: Visit方法测试 ===
void Unit8_VisitMethodTest(itbb::IndustrialFramework& framework) {
  std::cout << "[Unit8] 测试Visit方法..." << std::endl;

  try {
    framework.SubmitTask([]() {
      std::this_thread::sleep_for(1s);
      std::cout << "[Unit8] 执行Visit方法测试..." << std::endl;

      // 创建测试数据
      itbb::TbbDataValue int_value(42);
      itbb::TbbDataValue string_value(std::string("Test"));

      // 测试Visit方法
      int_value.Visit([](const auto& value) {
        using T = std::decay_t<decltype(value)>;
        if constexpr (std::is_same_v<T, int32_t>) {
          std::cout << "[Unit8] Visit test - int32: " << value << std::endl;
        }
      });

      string_value.Visit([](const auto& value) {
        using T = std::decay_t<decltype(value)>;
        if constexpr (std::is_same_v<T, std::string>) {
          std::cout << "[Unit8] Visit test - string: " << value << std::endl;
        }
      });

      std::cout << "[Unit8] Visit方法测试完成" << std::endl;
    });

    std::cout << "[Unit8] Visit方法测试任务已提交" << std::endl;
  } catch (const std::exception& e) {
    std::cout << "[Unit8] 异常: " << e.what() << std::endl;
  }
}

// === 独立单元9: 性能监控 ===
void Unit9_PerformanceMonitoring(
    itbb::IndustrialFramework& framework,
    std::shared_ptr<itbb::TbbAdwinDevice> adwin_device) {
  std::cout << "[Unit9] 测试性能监控..." << std::endl;

  try {
    framework.AddPeriodicTask(
        "PerformanceReport", 3000ms, [&framework, adwin_device]() {
          auto metrics = framework.GetPerformanceMetrics();
          std::cout << "[Unit9] === 性能报告 === " << std::endl;
          std::cout << "[Unit9] 活跃线程数: " << metrics.active_threads
                    << std::endl;
          std::cout << "[Unit9] 任务执行数: " << metrics.tasks_executed
                    << std::endl;
          std::cout << "[Unit9] CPU利用率: " << std::fixed
                    << std::setprecision(1) << metrics.cpu_utilization << "%"
                    << std::endl;

          // 显示设备统计（如果设备已连接）
          if (adwin_device && adwin_device->IsConnected().load()) {
            auto& stats = adwin_device->GetConnectionStats();
            std::cout << "[Unit9] 设备操作总数: "
                      << stats.total_operations.load() << std::endl;
            std::cout << "[Unit9] 设备失败数: "
                      << stats.failed_operations.load() << std::endl;
          }
        });

    std::cout << "[Unit9] 性能监控任务已启动" << std::endl;
  } catch (const std::exception& e) {
    std::cout << "[Unit9] 异常: " << e.what() << std::endl;
  }
}

// === 独立单元10: 动态配置调整 ===
void Unit10_DynamicConfigAdjustment(itbb::IndustrialFramework& framework) {
  std::cout << "[Unit10] 测试动态配置调整..." << std::endl;

  try {
    framework.SubmitTask([&framework]() {
      std::this_thread::sleep_for(5s);

      auto& config = itbb::GlobalConfigManager::GetInstance();

      std::cout << "[Unit10] === 动态配置调整 ===" << std::endl;
      std::cout << "[Unit10] 调整线程数到12..." << std::endl;
      framework.SetMaxThreads(12);
      config.SetConfig("framework.max_threads", 12.0);

      std::this_thread::sleep_for(3s);

      std::cout << "[Unit10] 调整调度精度到1ms..." << std::endl;
      framework.SetSchedulerPrecision(1ms);
      config.SetConfig("framework.scheduler_precision", 1.0);

      std::this_thread::sleep_for(2s);

      std::cout << "[Unit10] 切换到调试模式..." << std::endl;
      config.SetConfig("system.mode", std::string("debug"));

      std::this_thread::sleep_for(2s);

      std::cout << "[Unit10] 恢复到生产模式..." << std::endl;
      config.SetConfig("system.mode", std::string("production"));

      std::cout << "[Unit10] 动态配置调整完成" << std::endl;
    });

    std::cout << "[Unit10] 动态配置调整任务已提交" << std::endl;
  } catch (const std::exception& e) {
    std::cout << "[Unit10] 异常: " << e.what() << std::endl;
  }
}

// === 主函数 ===
int main() {
  try {
    std::cout << "=== TBB模块化测试启动 ===" << std::endl;

    itbb::IndustrialFramework framework;

    // 初始化配置
    auto& config = itbb::GlobalConfigManager::GetInstance();
    config.SetConfig("framework.max_threads", 8.0);
    config.SetConfig("framework.scheduler_precision", 5.0);
    config.SetConfig("system.version", std::string("1.0.0"));
    config.SetConfig("system.mode", std::string("production"));

    // 初始化框架
    framework.Initialize();
    std::cout << "框架初始化完成，当前线程数: "
              << tbb::info::default_concurrency() << std::endl;

    // 创建ADwin设备
    itbb::TbbAdwinConfig adwin_config;
    adwin_config.ip_address = "192.168.1.100";
    adwin_config.port.store(6543);
    adwin_config.timeout.store(5000ms);
    adwin_config.max_retries.store(3);
    adwin_config.enable_keepalive.store(true);
    adwin_config.enable_cache.store(true);
    adwin_config.cache_ttl.store(10ms);

    auto adwin_device =
        std::make_shared<itbb::TbbAdwinDevice>("ADwin-1", adwin_config);

    // 连接设备
    std::cout << "正在连接ADwin设备..." << std::endl;
    auto connect_future = adwin_device->ConnectAsync();

    // 测试每个独立单元
    std::cout << "=== 开始模块化测试 === " << std::endl;

    // 单元1: 连接进度显示
    Unit1_ConnectionProgress(framework, connect_future);

    // 等待连接完成
    bool connected = connect_future.get();
    if (connected) {
      std::cout << "[V] ADwin设备连接成功!" << std::endl;

      // 单元2: 高频数据采集
      Unit2_HighFreqDataCollection(framework, adwin_device);

      // 单元3: 设备健康监控
      Unit3_DeviceHealthMonitoring(framework, adwin_device);

      // 单元4: 批量数据处理
      Unit4_BatchDataProcessing(framework, adwin_device);

      // 单元5: 数据写入
      Unit5_DataWriting(framework, adwin_device);

      // 单元6: 进程控制测试
      Unit6_ProcessControl(framework, adwin_device);

      // 单元7: 参数批量读取
      Unit7_BatchParameterReading(framework, adwin_device);

      // 单元9: 性能监控
      Unit9_PerformanceMonitoring(framework, adwin_device);
    } else {
      std::cout << "[X] ADwin设备连接失败!" << std::endl;
    }

    // 单元8: Visit方法测试（不需要设备）
    Unit8_VisitMethodTest(framework);

    // 单元10: 动态配置调整（不需要设备）
    Unit10_DynamicConfigAdjustment(framework);

    // 等待用户输入
    std::cout << "=== 所有测试单元已启动 === " << std::endl;
    std::cout << "输入 'q' 退出程序: " << std::endl;

    char command;
    while (std::cin >> command && command != 'q') {
      std::cout << "输入 'q' 退出程序: " << std::endl;
    }

    // 关闭框架
    std::cout << "正在关闭框架..." << std::endl;
    framework.Shutdown();
    std::cout << "[V] 框架已安全关闭" << std::endl;
  } catch (const std::exception& e) {
    std::cerr << "[X] 框架错误: " << e.what() << std::endl;
    return 1;
  }

  return 0;
}